import 'package:dio/dio.dart';
import 'package:jm_flutter_common/jm_flutter_common.dart';
import 'package:universal_io/io.dart';

import '../common.dart';

export 'result.dart';
export 'server_result.dart';
export 'my_url.dart';

typedef SuccessCallback = void Function(dynamic data);
typedef FailCallback = void Function(String msg);
typedef DownloadCallback = void Function(int count, int total);

enum ApiMethod {
  get,
  post,
  head,
}

enum ApiError {
  timeOut,
}

Dio initDio() {
  BaseOptions _baseOptions =
      BaseOptions(connectTimeout: const Duration(seconds: 15));
  Dio dio = Dio(_baseOptions);
  // (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate  = (client) {
  //   client.badCertificateCallback=(X509Certificate cert, String host, int port){
  //     // if(cert.pem==PEM){ // Verify the certificate
  //     //   return true;
  //     // }
  //     logd("Api", "cert:"+cert.pem);
  //     return true;
  //   };
  // };

  // dio.interceptors
  //     .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
  //   print('走网络请求了设置头部了');
  //   // options.queryParameters['Authorization'] =
  //   //     SpUtil.getString('token', defValue: '');
  //   return options;
  // }));
  return dio;
}

class Api {
  static const tag = "Api";
  static final Dio _dio = initDio();

  static Future<Response?> upload(String path, String filepath, String filename,
      {Map<String, dynamic>? headers, Map<String, dynamic>? body}) async {
    FormData formData;
    MultipartFile multipartFile =
        await MultipartFile.fromFile(filepath, filename: filename);
    if (body != null) {
      formData = FormData.fromMap({
        ...body,
        'file': multipartFile,
      });
    } else {
      formData = FormData.fromMap({
        'file': multipartFile,
      });
    }

    return request(path,
        method: ApiMethod.post, body: formData, headers: headers);
  }

  static Future<Response?> get<T>(
    String path, {
    Object? data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
  }) async {
    try {
      //logd(tag, "网络请求开始:$path");
      final response =
          await _dio.get(path, data: data, queryParameters: queryParameters);
      //logd(tag, "网络请求结束:$path");
      return response;
    } on DioException catch (e) {
      // 处理Dio特定的异常
      if (e.error is SocketException) {
        logw(tag, "网络错误: ${e.error}");
      } else {
        logw(tag, "请求错误: ${e.error}");
      }
    } catch (e) {
      logw(tag, "网络错误:$e");
      return null;
    }
    return null;
  }

  static Future<Response?> request(
    path, {
    ApiMethod method = ApiMethod.get,
    Map<String, dynamic>? headers,
    Map<String, dynamic>? query,
    dynamic body,
  }) async {
    Response? result;
    try {
      if (method == ApiMethod.get) {
        result = await _dio.get(path,
            queryParameters: query, options: Options(headers: headers));
      } else if (method == ApiMethod.post) {
        result = await _dio.post(path,
            queryParameters: query,
            data: body,
            options: Options(headers: headers));
      } else if (method == ApiMethod.head) {
        result = await _dio.head(path,
            queryParameters: query, options: Options(headers: headers));
      }

      return result;
    } catch (e) {
      logw(tag, "网络错误: $path, $e");
      return null;
      // 非具体类型
      //print('Something really unknown: $e');
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<Result> serverRequest(
    String path, {
    Map<String, dynamic>? headers,
    Map<String, dynamic>? data,
    dynamic body,
    String? authorization,
    String? contentType,
    bool post = true,
    bool logcat = false,
  }) async {
    Response? response;
    var startTime = DateTime.now().millisecondsSinceEpoch;
    final options = Options(
        headers:
            authorization != null ? {'Authorization': authorization} : headers,
        contentType: contentType ?? Headers.jsonContentType);

    try {
      if (post) {
        response = await _dio.post(path, data: data, options: options);
      } else {
        response =
            await _dio.get(path, queryParameters: data, options: options);
      }

      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      Result result = Result.fromJsonResponse(response);
      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }
      return result;
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, $e");

      return Result.fromNetworkError(e.toString());
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<Result> serverUploadForBytes(String path,
      {required List<int> fileData,
      required String fileName,
      Map<String, dynamic>? data,
      bool logcat = false}) async {
    FormData formData;
    MultipartFile multipartFile =
        MultipartFile.fromBytes(fileData, filename: fileName);
    if (data != null) {
      formData = FormData.fromMap({
        ...data,
        'file': multipartFile,
      });
    } else {
      formData = FormData.fromMap({
        'file': multipartFile,
      });
    }

    Response? response;
    final startTime = DateTime.now().millisecondsSinceEpoch;
    try {
      response = await _dio.post(path, data: formData);

      final timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      Result result = Result.fromJsonResponse(response);
      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }
      return result;
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, $e");
      return Result.fromNetworkError(e.toString());
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }

  static Future<File?> downloadFile(String path,
      {required String savePath,
      bool logcat = false,
      DownloadCallback? callback}) async {
    Response? response;
    final startTime = DateTime.now().millisecondsSinceEpoch;
    try {
      //response = await _dio.post(path, data: formData);
      response = await _dio.download(path, savePath,
          onReceiveProgress: (count, total) {
        if (callback != null) {
          callback(count, total);
        }
      });

      final timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      if (logcat) {
        logd(tag, "请求完成: ${timeConsuming}ms, $path, $response");
      }

      if (response.statusCode != 200) {
        logw(tag, "状态错误: ${timeConsuming}ms, $path, $response");
      }

      return null;
    } catch (e) {
      var timeConsuming = DateTime.now().millisecondsSinceEpoch - startTime;
      logw(tag, "网络错误: ${timeConsuming}ms, $path, $e");
      return null;
    } finally {
      //logd(tag,'网络请求结束:'+path);
    }
  }
}
